package com.caishi.lkx.user.login;

import cn.hutool.core.util.StrUtil;
import com.caishi.lkx.user.dto.LoginDto;
import com.caishi.lkx.user.ienum.type.UserType;
import com.caishi.lkx.user.model.IUserModel;
import com.caishi.lkx.user.model.LoginInfoModel;
import com.caishi.lkx.user.model.UserModel;
import com.caishi.lkx.user.service.ILoginInfoService;
import com.caishi.lkx.user.service.IUserService;
import com.caishi.lkx.user.service.impl.UserServiceImpl;
import com.zzw.common.SpringContextHolder;
import com.zzw.common.entity.impl.BaseEntity;
import com.zzw.common.exception.BizException;
import com.zzw.common.exception.BizRuntimeException;
import com.zzw.common.service.TypeServiceRouter;
import com.caishi.lkx.user.UserResultCode;

import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * @author by keray
 * date:2019/8/1 10:42
 */
public interface LoginService {

    /**
     * 用户登录
     *
     * @param loginDto 登录信息
     * @return 登录账户
     * @throws BizException
     */
    LoginInfoModel loginBase(LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) throws BizException;

    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2021/6/8 10:21 上午</h3>
     * 通过登录信息注册
     * </p>
     *
     * @param loginInfoModel loginType 必传 account必传
     * @param userModel      userType 必传
     * @return <p> {@link IUserModel<?>} </p>
     * @throws
     */
    @Transactional(rollbackFor = Exception.class)
    default IUserModel<?> register(LoginInfoModel loginInfoModel, IUserModel<?> userModel) throws BizException {
        IUserService userService = TypeServiceRouter.router(UserType.int2Obj(userModel.getUserType()));
        IUserModel registerModel = userService.register(userModel);
        loginInfoModel.setUserId(userModel.getId());
        SpringContextHolder.getBean(ILoginInfoService.class).userAddNewLogin(loginInfoModel.getAccount(), LoginService.passwordEncryption(loginInfoModel.getCertificate()),
                loginInfoModel.getLoginType(), registerModel.getId());
        return registerModel;
    }

    default void code(String phone, HttpServletRequest request, HttpServletResponse response) {
    }

    default void  loginFail(LoginInfoModel infoModel, LoginDto loginDto) {
        LoginServiceComposite loginServiceComposite = SpringContextHolder.getBean(LoginServiceComposite.class);
        loginServiceComposite.loginFail(infoModel, loginDto);
    }

    /**
     * 校验登录信息
     *
     * @param infoModel
     * @param loginDto
     * @return
     * @throws BizException
     */
    default LoginInfoModel checkLoginInfo(LoginInfoModel infoModel, LoginDto loginDto) throws BizException {
        if (infoModel == null) {
            throw new BizException(UserResultCode.loginAuthFail);
        }
        if (loginDto.getUserType() != null) {
            UserServiceImpl userService = SpringContextHolder.getBean(UserServiceImpl.class);
            if (!userService.userIsHaveRole(infoModel.getUserId(), loginDto.getUserType())) {
                throw new BizException(UserResultCode.loginInfoNotFound);
            }
        }
        if (loginDto.getUserTypes() != null && loginDto.getUserTypes().length > 0) {
            UserServiceImpl userService = SpringContextHolder.getBean(UserServiceImpl.class);
            UserModel userModel = userService.selectOne(userService.wrappers().select(UserModel::getUserType).eq(BaseEntity::getId, infoModel.getUserId()));
            if (!UserType.intAnyHave(userModel.getUserType(), loginDto.getUserTypes())) {
                throw new BizException(UserResultCode.loginInfoNotFound);
            }
        }
        if (infoModel.getLock()) {
            loginFail(infoModel, loginDto);
            throw new BizRuntimeException(UserResultCode.loginInfoIsLock);
        }
        if (!infoModel.getEnable()) {
            loginFail(infoModel, loginDto);
            throw new BizRuntimeException(UserResultCode.loginInfoNotEnable);
        }
        return infoModel;
    }

    default List<UserType> getDtoUserTypes(LoginDto loginDto) {
        var userTypes = new LinkedList<UserType>();
        if (loginDto.getUserTypes() != null) {
            userTypes.addAll(Arrays.asList(loginDto.getUserTypes()));
        }
        if (loginDto.getUserType() != null) {
            userTypes.add(loginDto.getUserType());
        }
        return userTypes;
    }

    default LoginInfoModel doLogin(LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) throws BizException {
        return null;
    }

    static String passwordEncryption(String inputPass) {
        if (StrUtil.isBlank(inputPass)) {
            return null;
        }
        if (inputPass.length() < 64) {
            return inputPass;
        }
        return UsernameLoginServiceImpl.decryptStr(inputPass);
    }
}
